/**
 * @file crypt.c
 * @brief Cypher and Decypher functions used in the option cypher | dechyper.
 * @version 1.0
 * @date Nov-2011
 * @author Leonardo Lino 2101101
 * @author Joaquim Ferreira 2101104
 */

#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

#include "debug.h"
#include "crypt.h"
#include "files.h"
#include "memory.h"

/** @brief CYPHER 1 - A constant to use for define a type. */
#define CYPHER 1
/** @brief DECYPHER 2 - A constant to use for define a type. */
#define DECYPHER 2

/** @brief This function cypher a file from a given table.*/
void cypher (const char *table, const char *filename, int type)
{
  int char_filename;
  int j;
  int newChar;
  char **tabMem;
  int cntLine; /**< @brief Number of lines in table. Needed for several other functions.*/

  /**< @brief Used to load our entire table into memory for faster action.*/
  tabMem = tableLoader (table, &cntLine); 

  FILE *file_ptr = MY_FOPEN (filename, "r+");

  while (char_filename != EOF && G_continue) {
    char_filename = fgetc (file_ptr);

    newChar = letterReplace (char_filename, tabMem, cntLine, type);

    if (char_filename != EOF) {
      fseek (file_ptr, -1, SEEK_CUR);
      fputc (newChar, file_ptr);
    }

    if (char_filename == '\n')
      G_proc_lines++;
  }

  for (j = 0; j < cntLine; ++j)
    MY_FREE (tabMem[j]);
    
  MY_FREE (tabMem);
  fclose (file_ptr);
}

/** @brief This function receives a character, searches in the filetable for it then returns it's replacement.*/
char letterReplace (char letter, char **array, int cntLine, int type)
{
  int i;
  
  if (letter == ' ' || letter == ',' || letter == '.')
    return letter;
  for (i = 0; i < cntLine; i++) {
    if (type == CYPHER) {
      if (letter == array[i][0])
	return array[i][1];
    }
    if (type == DECYPHER) {
      if (letter == array[i][1])
	return array[i][0];
    }
  }

  return letter;
}

/** @brief This function copies the characters from the table from file to the table in memory.*/
char **tableLoader (const char *table, int *p_cntLine)
{
  int i = 0;
  int j = 0;
  int cntLine = 1;
  char buffer[100];
  size_t len = 0;
  ssize_t read;
  char **array = NULL;
  char *line = NULL;

  FILE *table_ptr = MY_FOPEN (table, "r");

  /**< @brief Count number of lines in table file. To be used for malloc.*/
  while ((fgets (buffer, 5, table_ptr)) != NULL) {
    cntLine++;
  }
  /**< @brief Reset file pointer to beginning of file.*/
  fseek (table_ptr, 0, SEEK_SET);

  array = (char **) MY_MALLOC (cntLine * sizeof (char *));
  
  for (j = 0; j < cntLine; ++j)
    array[j] = (char *) MY_MALLOC ((2) * sizeof (char));

  while ((read = getline (&line, &len, table_ptr)) != -1) {
    array[i][0] = line[0];
    array[i][1] = line[2];
    i++;
  }

  fclose (table_ptr);
  *p_cntLine = cntLine;
  return array;
}
